use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use ed25519_dalek::{Signer, SigningKey, Verifier, VerifyingKey};
use crate::{read_from_file_or_console, TextSignFormat};


pub fn process_sign(input: &str, key: &str, format: TextSignFormat) -> anyhow::Result<String> {
    let data = read_from_file_or_console("请输入需要签名的字符:".to_string(), input.to_string());

    let key = read_from_file_or_console("请输入签名使用的密钥:".to_string(), key.to_string());

    if key.len() != 32 {
        panic!("密码长度必须是32位")
    }

    let res = match format {
        TextSignFormat::Blake3 => {
            let blake3key = Blake3key::new(key);
            blake3key.sign(&data)
        }
        // TextSignFormat::Ed22519 => {
        //     let ed225 = Ed25519key::new(key);
        //     ed225.sign(&data)
        // }
    };
    res
}


pub fn process_verify(input: &str, key: &str, sign: &str, format: TextSignFormat) -> anyhow::Result<bool> {
    let data = read_from_file_or_console("请输入需要签名的字符:".to_string(), input.to_string());

    let key = read_from_file_or_console("请输入签名使用的密钥:".to_string(), key.to_string());

    let sign = read_from_file_or_console("请输入签名:".to_string(), sign.to_string());

    let res = match format {
        TextSignFormat::Blake3 => {
            let blake3key = Blake3key::new(key);

            blake3key.verify(data.as_str(), sign.as_str())
        }

        // TextSignFormat::Ed22519 => {
        //     let ed225 = Ed25519Verify::new(key);
        //
        //     ed225.verify(data.as_str(), sign.as_str())
        // }
    };

    res
}


trait TextSign {
    fn sign(&self, data: &str) -> anyhow::Result<String>;
}

trait TextVerify {
    fn verify(&self, data: &str, sign: &str) -> anyhow::Result<bool>;
}

struct Blake3key {
    key: [u8; 32],
}


impl Blake3key {
    fn new(key: String) -> Blake3key {
        println!("key is {}", key);
        let temp = key.as_bytes().to_vec();

        println!("temp is {:?}", temp.clone());
        let aa = temp.try_into().unwrap();

        println!("aa is {:?}", aa);

        let blake = Blake3key {
            key: aa
        };
        blake
    }
}


impl TextVerify for Blake3key {
    fn verify(&self, data: &str, sign: &str) -> anyhow::Result<bool> {
        let str = self.sign(data);

        Ok(str? == sign)
    }
}


impl TextSign for Blake3key {
    fn sign(&self, data: &str) -> anyhow::Result<String> {
        let hash = blake3::keyed_hash(&self.key, &data.as_bytes());

        let str = URL_SAFE_NO_PAD.encode(hash.as_bytes().to_vec());
        Ok(str)
    }
}


struct Ed25519key {
    key: SigningKey,
}

struct Ed25519Verify {
    key: VerifyingKey,
}


impl Ed25519key {
    fn new(key: String) -> Ed25519key {
        let ed22519 = Ed25519key {
            key: SigningKey::try_from(key.as_bytes()).unwrap()
        };
        ed22519
    }
}


impl Ed25519Verify {
    fn new(key: String) -> Ed25519Verify {
        println!("key is {}", key);
        let temp = key.as_bytes().to_vec();

        println!("temp is {:?}", temp.clone());
        let aa: [u8; 32] = temp.try_into().unwrap();

        println!("aa is {:?}", aa);


        Ed25519Verify {
            key:deserialize(key.as_bytes()).unwrap()
        }
    }
}

use bincode::deserialize;

impl TextVerify for Ed25519Verify {
    fn verify(&self, data: &str, sign: &str) -> anyhow::Result<bool> {
        let message: &[u8] = data.as_bytes();
        let decoded_verifying_key: VerifyingKey = self.key;
        let decoded_signature = deserialize(sign.as_bytes()).unwrap();

        let verified: bool = decoded_verifying_key.verify(&message, &decoded_signature).is_ok();

        Ok(verified)
    }
}


impl TextSign for Ed25519key {
    fn sign(&self, data: &str) -> anyhow::Result<String> {
        let ed25519_sign = self.key.sign(data.as_bytes());

        Ok(ed25519_sign.to_string())
    }
}